package betower

import (
	"database/sql"
	"go.uber.org/zap"
	"time"
	"wzgames/internal/client"
	"wzgames/internal/constant"
	"wzgames/internal/gdao/stmdao"
	"wzgames/internal/gloader"
	"wzgames/internal/model/statement"
	"wzgames/pkg/common/timingwheel"
	"wzgames/pkg/components/mysql"
	"wzgames/pkg/logger"
)

// 流水版本管理

type StmVerMgr struct {
	stmDs *mysql.DS

	t0 time.Duration
	t1 time.Duration
	t2 time.Duration

	tim *timingwheel.Timer

	limit int32
}

func (sv *StmVerMgr) Init() {
	sv.stmDs = gloader.CommMgr().GetDBProxy(constant.MysqlOfBHistory)
	sv.t0 = time.Millisecond * 100
	sv.t1 = time.Second
	sv.t2 = time.Second * 3
	sv.limit = 100
}

func (sv *StmVerMgr) Start() {
	sv.next(sv.t1)
}

func (sv *StmVerMgr) clearTimer() {
	if sv.tim != nil {
		sv.tim.Stop()
		sv.tim = nil
	}
}

func (sv *StmVerMgr) Stop() {
	sv.clearTimer()
}

func (sv *StmVerMgr) next(t time.Duration) {
	sv.clearTimer()
	sv.tim = TimerAfter(t, sv.process, nil)
}

func (sv *StmVerMgr) process(args interface{}) {
	data := sv.queryZeroList()
	if data == nil {
		sv.next(sv.t2)
		return
	}
	l := len(data)
	if l == 0 {
		sv.next(sv.t2)
		return
	}
	maxId := client.GetID(3102, uint64(l))
	if maxId == 0 {
		sv.next(sv.t1)
		return
	}
	c := uint64(0)
	for i := l - 1; i >= 0; i-- {
		data[i].VIdx = maxId - c
		c++
	}
	r := sv.updateZeroList(data)
	if l < int(sv.limit) {
		sv.next(sv.t1)
	} else {
		if r == 0 {
			sv.next(sv.t2)
		} else {
			sv.next(sv.t0)
		}
	}
}

func (sv *StmVerMgr) queryZeroList() []*statement.StmVerIdx {
	dao := stmdao.StmDao{Driver: sv.stmDs.Ds()}
	ret, err := dao.GetStatementsZeroVIdx(sv.limit)
	if err != nil {
		if err != sql.ErrNoRows {
			logger.Error("[BetTower] query zero ver statements fail on GetStatementsZeroVIdx", zap.Error(err))
			return nil
		}
	}

	return ret
}

func (sv *StmVerMgr) updateZeroList(data []*statement.StmVerIdx) int64 {
	dao := stmdao.StmDao{Driver: sv.stmDs.Ds()}
	c, err := dao.InsertStatementsZeroVIdx(data)
	if err != nil {
		logger.Error("[BetTower] update zero ver statements fail on InsertStatementsZeroVIdx", zap.Error(err))
	}

	return c
}
